/******************************************************************************/
/* File: dataStore.cpp                                                        */
/******************************************************************************/

#include "dataStore.h"
#include <string.h>

// dataStore 静态变量定义 -- CtrlClient
GeneralSetting DataStore::generalSetting;
Mutex DataStore::threadIdThreadMapMutex;
Mutex DataStore::connectionThreadIdMutex;
Mutex DataStore::threadIdConfMapMutex;
std::map<ConnectionInfo*, pthread_t> DataStore::connectionThreadIdMap;
std::map<pthread_t, ThreadConf *> DataStore::threadIdConfMap;
std::map<pthread_t, Thread *> DataStore::threadIdThreadMap;

// dataStore 静态变量定义 -- CtrlServer
std::list<TCPSocket *> DataStore::clientList;
std::map<CtrlClientInfo *, TCPSocket *> DataStore::clientSocketMap;
std::map<TCPSocket *, std::list<FlowInfo *> > DataStore::clientFlowsMap;

// 比较函数
bool CompareConnInfo(ConnectionInfo *src, ConnectionInfo *dst) {
    if( (src->iProto == dst->iProto) && (src->iRole == dst->iRole) &&
        (src->iSenderPort == dst->iSenderPort) && (src->iRecverPort == dst->iRecverPort) &&
        (strcmp(src->sSenderIP, dst->sSenderIP) == 0) &&
        (strcmp(src->sRecverIP, dst->sRecverIP) == 0) ) {
        return true;
    }
    
    return false;
}

// dataStore 静态函数定义 -- CtrlClient
pthread_t DataStore::FindFlowThread(ConnectionInfo *target) {
    connectionThreadIdMutex.Lock();
    
    pthread_t tid = -1;
    
    std::map<ConnectionInfo *, pthread_t>::iterator iter = connectionThreadIdMap.begin();
    while(iter != connectionThreadIdMap.end()) {
        if(CompareConnInfo(target, iter->first) == true) {
            tid = iter->second;
            break;
        }
        
        ++iter;
    }
    
    connectionThreadIdMutex.Unlock();
    
    return tid;
}

ThreadConf* DataStore::FindFlowThreadConf(pthread_t pid) {
    threadIdConfMapMutex.Lock();

    ThreadConf *ptc = NULL;
    std::map<pthread_t, ThreadConf *>::iterator iter;
    iter = threadIdConfMap.find(pid);
    if (iter != threadIdConfMap.end())
        ptc = iter->second;

    threadIdConfMapMutex.Unlock();
    
    return ptc;
}

void DataStore::AddNewFlowThread(Thread *pt, ConnectionInfo *pci, ThreadConf *ptc) {
    
    std::cout << "In AddNewFlowThread..." << std::endl;
    pthread_t myID = pt->GetThreadID();
    
    connectionThreadIdMutex.Lock();
    connectionThreadIdMap.insert(std::pair<ConnectionInfo*, pthread_t> (pci, myID));
    connectionThreadIdMutex.Unlock();
    
    threadIdConfMapMutex.Lock();
    threadIdConfMap.insert(std::pair<pthread_t, ThreadConf *> (myID, ptc));
    threadIdConfMapMutex.Unlock();
    
    threadIdThreadMapMutex.Lock();
    threadIdThreadMap.insert(std::pair<pthread_t, Thread *> (myID, pt));
    threadIdThreadMapMutex.Unlock();
    
    std::cout << "End AddNewFlowThread..." << std::endl;
}

void DataStore::RemoveFlowThread(ConnectionInfo *target) {
    pthread_t targetID;
    
    std::cout << "In RemoveFlowThread..." << std::endl;
    
    connectionThreadIdMutex.Lock();
    ConnectionInfo *pciRemoval;
    std::map<ConnectionInfo *, pthread_t>::iterator iter1 = connectionThreadIdMap.begin();
    while(iter1 != connectionThreadIdMap.end()) {
        if(CompareConnInfo(target, iter1->first) == true) {
            targetID = iter1->second;
            pciRemoval = iter1->first;
            connectionThreadIdMap.erase(iter1);
            break;
        }
        ++iter1;
    }
    delete pciRemoval;
    connectionThreadIdMutex.Unlock();
    
    threadIdConfMapMutex.Lock();
    ThreadConf *ptcRemoval;
    std::map<pthread_t, ThreadConf *>::iterator iter2;
    iter2 = threadIdConfMap.find(targetID);
    if(iter2 != threadIdConfMap.end()){
        ptcRemoval = iter2->second;
        threadIdConfMap.erase(iter2);
    }
    delete ptcRemoval;
    threadIdConfMapMutex.Unlock();
    
    threadIdThreadMapMutex.Lock();
    Thread *ptRemoval;
    std::map<pthread_t, Thread *>::iterator iter3;
    iter3 = threadIdThreadMap.find(targetID);
    if(iter3 != threadIdThreadMap.end()) {
        ptRemoval = iter3->second;
        threadIdThreadMap.erase(iter3);
    }
    delete ptRemoval;
    threadIdThreadMapMutex.Unlock();
    
    std::cout << "End RemoveFlowThread..." << std::endl;
}

// 比较函数
bool CompareCtrlClientInfo(CtrlClientInfo *src, CtrlClientInfo *dst) {
    if( (src->iCtrlClientPort == dst->iCtrlClientPort) &&
        (strcmp(src->sCtrlClientIP, dst->sCtrlClientIP) == 0) ) {
        return true;
    }
    
    return false;
}

// dataStore 静态函数定义 -- CtrlServer
TCPSocket* DataStore::FindCtrlClientSocket(CtrlClientInfo *pcci) {
    
    TCPSocket *pts = NULL;
    std::map<CtrlClientInfo *, TCPSocket *>::iterator iter = clientSocketMap.begin();
    while(iter != clientSocketMap.end()) {
        if(CompareCtrlClientInfo(pcci, iter->first) == true) {
            pts = iter->second;
            break;
        }
        
        ++iter;
    }
    
    return pts;
}

TCPSocket* DataStore::SearchCtrlClientSocket(char *sCtrlClientIP) {
    
    TCPSocket *pts = NULL;
    std::map<CtrlClientInfo *, TCPSocket *>::iterator iter = clientSocketMap.begin();
    while(iter != clientSocketMap.end()) {
        if(strcmp(sCtrlClientIP, iter->first->sCtrlClientIP) == 0) {
            pts = iter->second;
            break;
        }
        
        ++iter;
    }
    
    return pts;
}

std::list<FlowInfo*> DataStore::FindCtrlClientFlows(TCPSocket *pts) {
    
    std::list<FlowInfo*> flowList;
    flowList.clear();
    
    std::map<TCPSocket *, std::list<FlowInfo*> >::iterator iter;
    iter = clientFlowsMap.find(pts);
    if(iter == clientFlowsMap.end())
        return flowList;
    
    return iter->second;
}

void DataStore::AddNewCtrlClient(TCPSocket *pts) {
    
    std::cout << "Accept new ctrl client.\n";
    
    char *localIP = pts->LocalHostName();
    int localPort = pts->LocalPortNumber();
    
    char *remoteIP = pts->RemoteHostName();
    int remotePort = pts->RemotePortNumber();
    
    std::cout << "\nSocket Details - Local Information :";
    std::cout << "\nHostName    : " << localIP;
    std::cout << "\nPort        : " << localPort << std::endl;
                    
    std::cout << "\nSocket Details - Remote Information :";
    std::cout << "\nHostName    : " << remoteIP; 
    std::cout << "\nPort        : " << remotePort << std::endl;
 
    std::cout << "\nAdding new connection into database......\n";
    
    CtrlClientInfo *pcci = new CtrlClientInfo();
    pcci->sCtrlClientIP = strdup(remoteIP);
    pcci->iCtrlClientPort = remotePort;
    pcci->sConnectedIP = strdup(localIP);
    pcci->iConnectedPort = localPort;
    
    clientList.push_back(pts);
    clientSocketMap.insert(std::pair<CtrlClientInfo*, TCPSocket*>(pcci, pts));
    
    std::list<FlowInfo *> tmpList;
    tmpList.clear();
    clientFlowsMap.insert(std::pair<TCPSocket*, std::list<FlowInfo*> >(pts, tmpList));
    
    std::cout << "Adding new connection into database completed.\n\n";
}

void DataStore::RemoveCtrlClient(TCPSocket *pts) {
        
    std::cout << "\nRemoving invalid connection from database......\n";
    
    std::list<TCPSocket*>::iterator iter1;
    for(iter1 = clientList.begin(); iter1 != clientList.end(); ++iter1) {
        if (*iter1 == pts) {
            clientList.erase(iter1);
            break;
        }
    }
    
    std::map<CtrlClientInfo*, TCPSocket*>::iterator iter2;
    for(iter2 = clientSocketMap.begin(); iter2 != clientSocketMap.end(); ++iter2) {
        if ((iter2->second) == pts) {
            clientSocketMap.erase(iter2);
            delete iter2->first;
            break;
        }
    }
    
    std::map<TCPSocket*, std::list<FlowInfo*> >::iterator iter3;
    iter3 = clientFlowsMap.find(pts);
    if(iter3 == clientFlowsMap.end())
        return;
    
    std::list<FlowInfo*>::iterator iter4;
    for(iter4 = (iter3->second).begin(); iter4 != (iter3->second).end(); ++iter4) {
        delete *iter4;
    }
    
    (iter3->second).clear();
    
    std::cout << "\nRemoving invalid connection from database completed.\n";
}

/******************************************************************************/
/* End File: dataStore.cpp                                                    */
/******************************************************************************/